package com.fuqiang.nightshopadmin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuqiang.nightshopadmin.bo.AdminUserDetails;
import com.fuqiang.nightshopadmin.mapper.IUmsAdminMapper;
import com.fuqiang.nightshopadmin.mapper.IUmsAdminRoleRelationMapper;
import com.fuqiang.nightshopadmin.model.vo.UmsAdminVO;
import com.fuqiang.nightshopadmin.service.IUmsAdminService;
import com.fuqiang.nightshopcommon.exception.ApiException;
import com.fuqiang.nightshopsecurity.utils.JwtTokenUtil;
import com.fuqiang.nightshopumsmodel.entity.UmsAdmin;
import com.fuqiang.nightshopumsmodel.entity.UmsAdminRoleRelation;
import com.fuqiang.nightshopumsmodel.entity.UmsResource;
import com.fuqiang.nightshopumsmodel.entity.UmsRole;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.*;

/**
 * <p>
 * 后台用户表 服务实现类
 * </p>
 *
 * @author fuqiang
 * @since 2020-04-14
 */
@Service
@AllArgsConstructor
public class UmsAdminServiceImpl extends ServiceImpl<IUmsAdminMapper, UmsAdmin> implements IUmsAdminService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class);
    private IUmsAdminMapper umsAdminMapper;
    private IUmsAdminRoleRelationMapper umsAdminRoleRelationMapper;
    private JwtTokenUtil jwtTokenUtil;
    private PasswordEncoder passwordEncoder;


    @Override
    public String login(String username, String password) {
        String token = null;
        //密码需要客户端加密后传递
        try{
            UserDetails userDetails = loadUserByUserName(username);
            // 对比密码是否正确
//            if(!passwordEncoder.matches(password,userDetails.getPassword())){
//                throw new BadCredentialsException("密码不正确");
//            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            token = jwtTokenUtil.generateToken(userDetails);
        }catch (AuthenticationException e){
            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

    @Override
    public UserDetails loadUserByUserName(String username) {
        UmsAdmin adminByUsername = getAdminByUsername(username);
        if(adminByUsername != null){
            // 查询角色拥有的资源
            List<UmsResource> resourceList = getResourceList(adminByUsername.getId());
            return new AdminUserDetails(adminByUsername,resourceList);
        }
        throw new UsernameNotFoundException("用户名或密码错误!");
    }

    @Override
    public UmsAdmin getAdminByUsername(String username) {
        QueryWrapper<UmsAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UmsAdmin::getUsername,username);
        UmsAdmin umsAdmin = umsAdminMapper.selectOne(queryWrapper);
        if(umsAdmin != null){
            return umsAdmin;
        }
        return null;
    }

    @Override
    public List<UmsResource> getResourceList(Long adminId) {
        return umsAdminRoleRelationMapper.getResourceList(adminId);
    }

    @Override
    public IPage<UmsAdmin> list(String keyword, Integer pageSize, Integer pageNum) {
        IPage<UmsAdmin> umsAdminIPage = queryAdminByUserNameAndPage(keyword, pageSize, pageNum);
        return umsAdminIPage;
    }

    @Override
    public List<UmsRole> getRoleList(Long adminId) {
        return umsAdminRoleRelationMapper.getRoleList(adminId);
    }

    @Override
    public int updateRole(Long adminId, List<Long> roleIds) {
        // 删除之前的对应关系
        QueryWrapper<UmsAdminRoleRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UmsAdminRoleRelation::getAdminId,adminId);
        umsAdminRoleRelationMapper.delete(queryWrapper);
        // 在插入新的对应关系
        if(!roleIds.isEmpty()){
            for (Long roleId : roleIds) {
                UmsAdminRoleRelation umsAdminRoleRelation = new UmsAdminRoleRelation();
                umsAdminRoleRelation.setAdminId(adminId);
                umsAdminRoleRelation.setRoleId(roleId);
                umsAdminRoleRelationMapper.insert(umsAdminRoleRelation);
            }
        }
        return 1;
    }

    @Override
    public UmsAdmin register(UmsAdminVO umsAdminVO) {
        // 启用多线程
        Future<UmsAdmin> umsAdminFuture = startThread(umsAdminVO.getUsername());
        UmsAdmin umsAdmin = new UmsAdmin();
        BeanUtils.copyProperties(umsAdminVO,umsAdmin);
        umsAdmin.setStatus(umsAdminVO.getStatus() == null ? 1 : umsAdminVO.getStatus());
        umsAdmin.setCreateTime(LocalDateTime.now());

        UmsAdmin umsAdminOld = null;
        try {
            umsAdminOld = umsAdminFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new ApiException(e.getMessage());
        } catch (ExecutionException e) {
            e.printStackTrace();
            throw new ApiException(e.getMessage());
        }
        if(umsAdminOld != null){
            throw new ApiException("用户名已存在!");
        }
        // 对密码加密
        umsAdmin.setPassword(passwordEncoder.encode(umsAdminVO.getPassword()));
        // 插入
        int insert = umsAdminMapper.insert(umsAdmin);
        return umsAdmin;
    }

    @Override
    public int update(Long id, UmsAdminVO umsAdminVO) {
        UmsAdmin umsAdmin = umsAdminMapper.selectById(id);
        String encode = passwordEncoder.encode(umsAdminVO.getPassword());
        // 与原密码相同不需要修改密码
        if(umsAdmin.getPassword().equals(encode)){
            umsAdminVO.setPassword(null);
        }else{
            // 密码加密存储
            umsAdminVO.setPassword(encode);
        }
        BeanUtils.copyProperties(umsAdminVO,umsAdmin);
        return umsAdminMapper.updateById(umsAdmin);
    }

    // 开启多线程
    private Future<UmsAdmin> startThread(String username){
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<UmsAdmin> submit = executorService.submit(new Callable<UmsAdmin>() {
            @Override
            public UmsAdmin call() throws Exception {
                // 查询是否有同名用户
                QueryWrapper<UmsAdmin> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(UmsAdmin::getUsername, username);
                UmsAdmin umsAdmin = umsAdminMapper.selectOne(queryWrapper);
                return umsAdmin;
            }
        });
        return submit;
    }

    private IPage<UmsAdmin> queryAdminByUserNameAndPage(String keyword, Integer pageSize, Integer pageNum){
        QueryWrapper<UmsAdmin> queryWrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(keyword)){
            queryWrapper.lambda().like(UmsAdmin::getUsername,keyword)
                    .or()
                    .like(UmsAdmin::getNickName,keyword);
        }

        Page<UmsAdmin> page = new Page<>(pageNum,pageSize);
        IPage<UmsAdmin> umsAdminIPage = umsAdminMapper.selectPage(page, queryWrapper);
        return umsAdminIPage;
    }
}
